﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Web;
using System.IO;
using System.Xml.Serialization;
using System.Xml;
using System.Linq;
using System.Net;
using System.Configuration;
using System.Threading;

namespace BarcodeHandlerForms
{
    public partial class BarcodeMainForm : Form
    {
        private static bool Listen = false;
        private static FileSystemWatcher fileSystemWatcher = new FileSystemWatcher();
        private static readonly string Prefix = "InputXML=";
        public static string SendUrl = string.IsNullOrWhiteSpace(Utils.GetConfiguration().AppSettings.Settings["RequestUrl"].Value) ? "http://mycflexibd02:8083/Service/wsWIP.asmx/GetEtResult" : Utils.GetConfiguration().AppSettings.Settings["RequestUrl"].Value;
        private static string Content = "<?xml version=\"1.0\" encoding=\"utf-16\"?><MfgOrder xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><PanelId>2022032823003001192G</PanelId><Lot>13362639</Lot></MfgOrder>";
        public static string ReadWriteDirectoryPath = string.IsNullOrWhiteSpace(Utils.GetConfiguration().AppSettings.Settings["ReadWriteDirectory"].Value) ? string.Format("{0}ReadWriteDirectory", AppDomain.CurrentDomain.BaseDirectory) : Utils.GetConfiguration().AppSettings.Settings["ReadWriteDirectory"].Value;
        public static string BackupDirectoryPath = string.IsNullOrWhiteSpace(Utils.GetConfiguration().AppSettings.Settings["BackupDirectory"].Value) ? string.Format("{0}BackupDirectory", AppDomain.CurrentDomain.BaseDirectory) : Utils.GetConfiguration().AppSettings.Settings["BackupDirectory"].Value;

        public static bool IsRequest = bool.Parse(Utils.GetConfiguration().AppSettings.Settings["isRequest"].Value);
        public static bool IsBackup = bool.Parse(Utils.GetConfiguration().AppSettings.Settings["isBackup"].Value);
        public static bool IsAlwaysWrite = bool.Parse(Utils.GetConfiguration().AppSettings.Settings["isAlwaysWrite"].Value);

        public BarcodeMainForm()
        {
            InitializeComponent();
            this.txtReadSrc.Text = ReadWriteDirectoryPath;
            this.txtBackupSrc.Text = BackupDirectoryPath;
            this.txtUrl.Text = SendUrl;
            this.ckbRequest.Checked = IsRequest;
            this.ckbBackup.Checked = IsBackup;
            this.ckbAlwaysWrite.Checked = IsAlwaysWrite;


            this.notifyIcon1.Visible = true;
            //this.Icon = Properties.Resources.black;

            #region 创建文件夹
            if (!Directory.Exists(ReadWriteDirectoryPath))
            {
                Directory.CreateDirectory(ReadWriteDirectoryPath);
            }

            if (!Directory.Exists(BackupDirectoryPath))
            {
                Directory.CreateDirectory(BackupDirectoryPath);
            }
            #endregion
        }

        /// <summary>
        /// 开始发送请求
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSend_Click(object sender, EventArgs e)
        {
            string readUrl = this.txtUrl.Text;
            if (!string.IsNullOrWhiteSpace(readUrl))
                SendUrl = readUrl;

            Listen = !Listen;
            if (Listen)
            {
                //this.Icon = Properties.Resources.green;
                this.notifyIcon1.Icon = Properties.Resources.green;
                this.btnSend.Text = "停止";
                //this.richTextOutput.AppendText(string.Format("------------------------------开始监听{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
            }
            else
            {
                //this.Icon = Properties.Resources.black;
                this.notifyIcon1.Icon = Properties.Resources.black;
                this.btnSend.Text = "开始";
                //this.richTextOutput.AppendText(string.Format("------------------------------结束监听{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
            }

            FileSystemEventHandler handlerFile = (sender1, e1) =>
            {
                string noTestBarcode = string.Empty;
                string barcode = string.Empty;
                string prevReadBarcode = string.Empty;

                try
                {
                    Thread.Sleep(100);
                    this.BeginInvoke(new Action(() =>
                    {
                        this.Icon = Properties.Resources.green;
                        this.notifyIcon1.Icon = Properties.Resources.green;

                        if (this.richTextOutput.GetLineFromCharIndex(this.richTextOutput.Text.Length) > 10000)
                            this.richTextOutput.Clear();
                        this.richTextOutput.AppendText(string.Format("------------------------------开始读取数据{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                    }));

                    string readContent = string.Empty;
                    using (StreamReader reader = File.OpenText(string.Format("{0}/Barcode.txt", ReadWriteDirectoryPath)))
                        barcode = reader.ReadToEnd();

                    string[] files = Directory.GetFiles(ReadWriteDirectoryPath).Where(p => !p.Contains("Barcode")).ToArray();

                    foreach (var file in files)
                        File.Delete(file);

                    string[] analysisArray = barcode.Replace("\r\n", "|").Split('|');

                    SendPanlInfoModel sendPanlInfoModel = new SendPanlInfoModel();
                    Enumerable.Range(0, analysisArray.Length / 2).ToList().ForEach(analy =>
                    {
                        foreach (string str in analysisArray)
                        {
                            string[] array = str.Split(':');
                            if ("barcode" == array[0].ToLower())
                            {
                                string code = array[1];
                                sendPanlInfoModel.PanelId = code;
                                code = code.Replace(" *", "");
                                noTestBarcode = string.Format("{0}{1}", noTestBarcode, string.IsNullOrWhiteSpace(noTestBarcode) ? code : string.Format(",{0}", code));
                            }
                            if ("lot" == array[0].ToLower())
                                sendPanlInfoModel.Lot = array[1];
                        }
                    });

                    var xmlSerializerWrite = new XmlSerializer(typeof(SendPanlInfoModel));
                    MemoryStream ms = new MemoryStream();
                    using (StreamWriter writer = new StreamWriter(ms))
                    {
                        xmlSerializerWrite.Serialize(writer, sendPanlInfoModel);
                        readContent = Encoding.Default.GetString(ms.GetBuffer());
                    }

                    this.BeginInvoke(new Action(() =>
                    {
                        this.richTextOutput.AppendText(string.Format("{0}\r\n", barcode));
                        this.richTextOutput.AppendText(string.Format("------------------------------结束读取数据{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                        this.richTextOutput.AppendText(string.Format("------------------------------开始接收{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                    }));
                    readContent = readContent.Replace(" *", "");
                    string content = "notest: *";
                    if (IsRequest)
                    {

                        byte[] bytes = Encoding.Default.GetBytes(string.Format("{0}{1}", Prefix, (string.IsNullOrWhiteSpace("readContent") ? Content : readContent)));
                        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(SendUrl);
                        //request.ServicePoint.ConnectionLimit = int.MaxValue;
                        request.Proxy = null;
                        request.Method = "POST";
                        request.ContentType = "application/x-www-form-urlencoded";
                        request.ContentLength = bytes.Length;
                        using (Stream stream = request.GetRequestStream())
                        {
                            stream.Write(bytes, 0, bytes.Length);
                        }

                        using (WebResponse response = request.GetResponse())
                        {
                            using (Stream readStream = response.GetResponseStream())
                            {
                                byte[] readBytes = new byte[4096];
                                readStream.Read(readBytes, 0, readBytes.Length);
                                content = HttpUtility.HtmlDecode(Encoding.Default.GetString(readBytes));
                            }
                        }
                        content = content.Replace("<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n", "");
                        content = content.Replace("<string xmlns=\"http://tempuri.org/\">", "");
                        content = content.Replace("</string>", "");
                        content = content.Replace("\0", "");

                        var xmlSerializer = new XmlSerializer(typeof(MfgOrder));
                        MfgOrder mfgOrder = null;
                        MfgOrders panelInfos = null;
                        using (Stream stream = new MemoryStream(Encoding.GetEncoding("utf-16").GetBytes(content)))
                        {
                            mfgOrder = xmlSerializer.Deserialize(stream) as MfgOrder;
                            stream.Seek(0, SeekOrigin.Begin);

                            xmlSerializer = new XmlSerializer(typeof(MfgOrders));
                            panelInfos = xmlSerializer.Deserialize(stream) as MfgOrders;
                        }
                        content = string.Format("notest:{0} *", string.Join(",", panelInfos.Select(x => x.PcsSeq).ToArray()));

                        this.BeginInvoke(new Action(() =>
                        {
                            if (mfgOrder != null)
                                this.richTextOutput.AppendText(string.Format("PanelId:{0} Lot:{1} TrackInQty:{2} IsSuccess:{3}\r\n", mfgOrder.PanelId, mfgOrder.Lot, mfgOrder.TrackInQty, mfgOrder.IsSuccess, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));

                            foreach (var panelInfo in panelInfos)
                                this.richTextOutput.AppendText(string.Format("PanelId:{0}\r\nPcsSeq:{1}\r\n", panelInfo.PanelId, panelInfo.PcsSeq, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                        }));
                    }
                    if (!string.IsNullOrWhiteSpace(noTestBarcode))
                    {
                        if (prevReadBarcode != noTestBarcode)
                        {
                            prevReadBarcode = noTestBarcode;
                            if (File.Exists(string.Format("{0}/{1}.txt", ReadWriteDirectoryPath, noTestBarcode)))
                                File.Delete(string.Format("{0}/{1}.txt", ReadWriteDirectoryPath, noTestBarcode));
                            File.WriteAllText(string.Format("{0}/{1}.txt", ReadWriteDirectoryPath, noTestBarcode), content);
                            if (IsBackup)
                            {
                                File.WriteAllText(string.Format("{0}/{2}.txt", BackupDirectoryPath, DateTime.Now.ToString("yyyyMMddHHmmssffffff"), noTestBarcode), content);
                            }
                        }
                    }

                    this.BeginInvoke(new Action(() =>
                    {
                        this.richTextOutput.AppendText(string.Format("------------------------------停止接收{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                        this.richTextOutput.Focus();
                    }));
                }
                catch (Exception ex)
                {
                    if (File.Exists(string.Format("{0}/{1}.txt", ReadWriteDirectoryPath, noTestBarcode)))
                        File.Delete(string.Format("{0}/{1}.txt", ReadWriteDirectoryPath, noTestBarcode));
                    if (!string.IsNullOrWhiteSpace(noTestBarcode) && IsAlwaysWrite)
                    {
                        File.WriteAllText(string.Format("{0}/{1}.txt", ReadWriteDirectoryPath, noTestBarcode), "notest: *");
                        File.WriteAllText(string.Format("{0}/{2}.txt", BackupDirectoryPath, DateTime.Now.ToString("yyyyMMddHHmmssffffff"), noTestBarcode), "notest: *");
                    }
                    this.BeginInvoke(new Action(() =>
                    {
                        //this.Icon = Properties.Resources.red;
                        this.notifyIcon1.Icon = Properties.Resources.red;
                        this.richTextOutput.AppendText(string.Format("{1}{0}", ex.ToString(), this.richTextOutput.Text.Length > 0 ? "\r\n" : ""));
                        this.richTextOutput.Focus();
                    }));
                }
            };

            fileSystemWatcher.Path = string.Format("{0}", ReadWriteDirectoryPath);
            fileSystemWatcher.Filter = "*Barcode.txt";
            if (Listen)
            {
                fileSystemWatcher.Created += handlerFile;
                fileSystemWatcher.Changed += handlerFile;
            }
            else
            {
                fileSystemWatcher.Created -= handlerFile;
                fileSystemWatcher.Changed -= handlerFile;
            }
            fileSystemWatcher.EnableRaisingEvents = Listen;
            if (Listen)
            {
                this.richTextOutput.AppendText(string.Format("------------------------------开始连接{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                Thread.Sleep(300);
                this.richTextOutput.AppendText(string.Format("------------------------------连接成功{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
            }
            else
            {
                this.richTextOutput.AppendText(string.Format("------------------------------关闭连接{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
                Thread.Sleep(200);
                this.richTextOutput.AppendText(string.Format("------------------------------关闭成功{0}------------------------------\r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss ffff")));
            }
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            MouseEventArgs mouseEventArgs = (MouseEventArgs)e;
            if (mouseEventArgs.Button == MouseButtons.Left)
            {
                if (this.WindowState == FormWindowState.Minimized)
                {
                    this.Show();
                    this.WindowState = FormWindowState.Normal;
                }
                else
                {
                    this.WindowState = FormWindowState.Minimized;
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BarcodeMainForm_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                Thread.Sleep(300);
                this.Hide();
            }
        }

        /// <summary>
        /// 退出
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void notifyIconMenuStrip_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void BarcodeMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult result = MessageBox.Show("确认关闭吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (result == DialogResult.OK)
            {
                this.notifyIcon1.Visible = false;
            }
            else 
            {
                e.Cancel = true;
            }
        }

        private void ToolStripMenuSelectReadPath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            folderBrowserDialog.Description = "请选择读取文件夹";
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                Configuration config = Utils.GetConfiguration();
                if (config != null)
                    config.AppSettings.Settings["ReadWriteDirectory"].Value = folderBrowserDialog.SelectedPath;
                config.SaveAs(config.FilePath, ConfigurationSaveMode.Modified, true);
                ReadWriteDirectoryPath = folderBrowserDialog.SelectedPath;
                this.txtReadSrc.Text = ReadWriteDirectoryPath;
            }
        }

        private void ToolStripMenuBackupPath_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            folderBrowserDialog.Description = "请选择备份文件夹";
            if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
            {
                Configuration config = Utils.GetConfiguration();
                if (config != null)
                    config.AppSettings.Settings["BackupDirectory"].Value = folderBrowserDialog.SelectedPath;
                config.SaveAs(config.FilePath, ConfigurationSaveMode.Modified, true);

                BackupDirectoryPath = folderBrowserDialog.SelectedPath;
                this.txtBackupSrc.Text = BackupDirectoryPath;
            }
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripMenuChangePassword_Click(object sender, EventArgs e)
        {
            PasswordForm passwordForm = new PasswordForm();
            passwordForm.ShowDialog();

            if (!passwordForm.isValidate)
                return;

            ChangePasswordForm changePasswordForm = new ChangePasswordForm();
            changePasswordForm.ShowDialog();
        }

        /// <summary>
        /// 关于我们
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripMenuAbout_Click(object sender, EventArgs e)
        {
            AboutBox aboutBox = new AboutBox();
            aboutBox.ShowDialog();
        }

        /// <summary>
        /// 路径设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripMenuSettings_Click(object sender, EventArgs e)
        {
            PasswordForm passwordForm = new PasswordForm();
            passwordForm.ShowDialog();

            if (!passwordForm.isValidate)
                return;

            SettingsForm settingsForm = new SettingsForm();
            settingsForm.ShowDialog();
            this.txtReadSrc.Text = ReadWriteDirectoryPath;
            this.txtBackupSrc.Text = BackupDirectoryPath;
            this.txtUrl.Text = SendUrl;
            this.ckbRequest.Checked = IsRequest;
            this.ckbBackup.Checked = IsBackup;
            this.ckbAlwaysWrite.Checked = IsAlwaysWrite;
        }
    }


    #region 模型
    public class PanelInfos
    {
        public string PanelId { get; set; }

        public int PcsSeq { get; set; }
    }

    [XmlRoot(ElementName = "MfgOrder")]
    public class SendPanlInfoModel
    {
        public string PanelId { get; set; }

        public string Lot { get; set; }
    }

    public class MfgOrder
    {
        public string PanelId { get; set; }
        public string Lot { get; set; }
        public string TrackInQty { get; set; }
        public string IsSuccess { get; set; }
    }

    [Serializable]
    [XmlType(AnonymousType = true)]
    [XmlRoot(ElementName = "MfgOrder")]
    public class MfgOrders : List<PanelInfos>
    {

    }

    //[XmlRoot(ElementName = "MfgOrder")]
    //public class SendPanelInfos : List<SendPanlInfoModel>
    //{

    //}
    #endregion
}
